package chooongg.base.utils

import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import androidx.annotation.IntDef
import chooongg.base.Utils
import java.math.BigDecimal
import kotlin.math.max

/**
 * 内存常量
 */
object MemoryConstants {

    const val BYTE = 1
    const val KB = 1024
    const val MB = 1048576
    const val GB = 1073741824

    @IntDef(BYTE, KB, MB, GB)
    annotation class Unit
}

private val hexDigits =
    charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F')

/**
 * 内存大小转字节大小
 *
 * @param memorySize 内存大小
 * @param unit       单位
 *  * [MemoryConstants.BYTE]
 *  * [MemoryConstants.KB]
 *  * [MemoryConstants.MB]
 *  * [MemoryConstants.GB]
 */
fun memorySize2Byte(memorySize: Long, @MemoryConstants.Unit unit: Int): Long {
    return if (memorySize < 0) -1 else memorySize * unit
}

/**
 * Long转文件大小语义化
 */
fun Long.formatFileSize(): String {
    val kiloByte = this / 1024.toDouble()
    val megaByte = kiloByte / 1024
    if (megaByte < 1) {
        return kiloByte.toBigDecimal().setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "KB"
    }
    val gigaByte = megaByte / 1024
    if (gigaByte < 1) {
        return megaByte.toBigDecimal().setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "MB"
    }
    val teraBytes = megaByte / 1024
    if (teraBytes < 1) {
        return megaByte.toBigDecimal().setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "G"
    }
    return teraBytes.toBigDecimal().setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "T"
}

/**
 * 字节大小转内存大小语义化
 */
fun byte2FitMemorySize(byteSize: Long): String {
    return when {
        byteSize < 0 -> "shouldn't be less than zero!"
        byteSize < MemoryConstants.KB -> String.format("%.3fB", byteSize.toDouble())
        byteSize < MemoryConstants.MB -> String.format(
            "%.3fKB",
            byteSize.toDouble() / MemoryConstants.KB
        )
        byteSize < MemoryConstants.GB -> String.format(
            "%.3fMB",
            byteSize.toDouble() / MemoryConstants.MB
        )
        else -> String.format("%.3fGB", byteSize.toDouble() / MemoryConstants.GB)
    }
}

/**
 * Drawable转Bitmap
 */
fun Drawable.toBitmap(): Bitmap? {
    if (this is BitmapDrawable) {
        if (this.bitmap != null) return this.bitmap
    }

    var bitmap: Bitmap?
    val width = max(intrinsicWidth, 2)
    val height = max(intrinsicHeight, 2)
    try {
        bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        setBounds(0, 0, canvas.width, canvas.height)
        draw(canvas)
    } catch (e: Throwable) {
        e.printStackTrace()
        bitmap = null
    }
    return bitmap
}

/**
 * Bitmap转Drawable.
 */
fun Bitmap.toDrawable(): Drawable? = BitmapDrawable(Utils.app.resources, this)